package com.spi.soconversion.base.data;

import java.util.List;
import java.io.File;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Random;

import org.w3c.dom.Document;

import com.spi.soconversion.Batch;
import com.spi.soconversion.base.MarshallingException;
import com.spi.soconversion.base.SOCException;
import com.spi.soconversion.base.definition.COFIOrderLine;
import com.spi.soconversion.base.definition.Charge;
import com.spi.soconversion.base.definition.ChildLine;
import com.spi.soconversion.base.definition.DerivedFrom;
import com.spi.soconversion.base.definition.HeaderCharge;
import com.spi.soconversion.base.definition.HeaderTax;
import com.spi.soconversion.base.definition.Item;
import com.spi.soconversion.base.definition.LineCharge;
import com.spi.soconversion.base.definition.LinePriceInfo;
import com.spi.soconversion.base.definition.LineTax;
import com.spi.soconversion.base.definition.OpenSalesOrderDefinition;
import com.spi.soconversion.base.definition.OrderExtension;
import com.spi.soconversion.base.definition.OrderLine;
import com.spi.soconversion.base.definition.OrderLineExtension;
import com.spi.soconversion.base.definition.OrderLineOption;
import com.spi.soconversion.base.definition.OrderLineRelationShip;
import com.spi.soconversion.base.definition.ParentLine;
import com.spi.soconversion.base.definition.ProductLine;
import com.spi.soconversion.base.definition.ProductServiceAssoc;
import com.spi.soconversion.base.definition.ServiceLine;
import com.spi.soconversion.base.handlers.OpenSalesConversionStatisticsHandler;
import com.spi.soconversion.dao.ChargeDAO;
import com.spi.soconversion.dao.ChargeDAOImpl;
import com.spi.soconversion.dao.OpenSalesOrderConstants;
import com.spi.soconversion.dao.OrderDAO;
import com.spi.soconversion.dao.OrderDAOImpl;
import com.spi.soconversion.dao.POSProvince;
import com.spi.soconversion.orders.OpenSalesOrderDefinitionMarshaller;
import com.spi.soconversion.orders.conversion.DeliveryMethod;
import com.spi.soconversion.orders.conversion.FulfillmentType;
import com.spi.soconversion.orders.conversion.ItemGroupCode;
import com.spi.soconversion.orders.conversion.ItemType;
import com.spi.soconversion.orders.conversion.LineType;
import com.spi.soconversion.orders.conversion.PromiseEndDate;
import com.spi.soconversion.orders.conversion.PromiseStartDate;
import com.spi.soconversion.orders.conversion.RestockingFeeCategory;
import com.spi.soconversion.orders.conversion.SalvageLine;
import com.spi.soconversion.util.ErrorConstants;
import com.spi.soconversion.util.ErrorMessageReader;
import com.spi.soconversion.util.MCFConverter;
import com.spi.soconversion.util.QueryConstants;
import com.spi.soconversion.util.QueryReader;
import com.spi.soconversion.util.ResourceProvider;
import com.spi.soconversion.util.SOCConstants;
import com.spi.soconversion.util.SOCFileWriter;
import com.spi.soconversion.util.SOCUtility;

/**
 * A class for processing open sales order conversion
 * 
 * @author XSPID41
 *
 */
public class OpenSalesOrderDataProcessor implements DataProcessor, OpenSalesOrderConstants {
	
    static private org.apache.commons.logging.Log log = 
        org.apache.commons.logging.LogFactory.getLog(OpenSalesOrderDataProcessor.class);
    
	private int d_batchSize;
	private int d_batchNum;
	private int d_totalRecProcessed;
	private String d_logFileName;
	private SOCFileWriter d_fileWriter;	
	private String d_xmlDirectory;
	private int d_xmlCounter;
	private int d_recordsFetched;
	private int d_ordersNotConverted;
	private ArrayList<Long> convertedOrdersList = new ArrayList<Long>();
	private ArrayList<Long> notConvertedOrdersList = new ArrayList<Long>();       
        
    private long returnOrderNumber;
    
	private OrderDAO orderDAO = new OrderDAOImpl();
	private ChargeDAO mcfDAO = new ChargeDAOImpl();
	private HashMap<String, String> leftSku2rightSku = new HashMap<String, String>();
	
	private HashMap<OrderLine, Integer> primeLineNoMap = new HashMap<OrderLine, Integer>();
	private HashMap<String, OrderLine> linesMap = new HashMap<String, OrderLine>();
	private HashMap<String, OrderLine> returnLinesMap = new HashMap<String, OrderLine>();
	private ArrayList<COFIOrderLine> exchangeLines = new ArrayList<COFIOrderLine>();
	private ArrayList<OpenSalesOrderDefinition> xmlList = new ArrayList<OpenSalesOrderDefinition>();
	private List<String>  furnitureCategories ;
	
	private ArrayList<LineCharge> lineChargesList = new ArrayList<LineCharge>(); 
	private HashMap<LineCharge, COFIOrderLine> lineChargesMap = new HashMap<LineCharge, COFIOrderLine>();
	
	int primeLineNo = 0;
	int derivedPrimeLineNo = 0;
	int olrParentPrimeLineNo = 0;
	int olfChildPrimeLineNo = 0;
	int psaProductPrimeLineNo = 0;
	int psaServicePrimeLineNo = 0;
	int randNum=0;
	
	private String retOrdNum;
	private String wrfeeCategories[]= {"501", "502", "504", "505", "506", "507", "508", "509", "510", "513", "514", "517", "518", "519", "520", "521", "522"};
	private Random rand = new Random();
	
	private OpenSalesConversionStatisticsHandler statisticsHandler;
	private Batch batch = null;
	private ResourceProvider provider;
	
	public OpenSalesOrderDataProcessor(String logFileName, SOCFileWriter fileWriter, Batch batch)
	throws SOCException {

		this.batch = batch;
		this.d_fileWriter = fileWriter;
		this.d_logFileName = logFileName;

		statisticsHandler= new OpenSalesConversionStatisticsHandler(d_logFileName, d_fileWriter);
		provider = ResourceProvider.getInstance();
		d_xmlDirectory = provider.getXmlOutputDirectory();
		
		d_batchNum=batch.getBatchNumber();
		d_batchSize=batch.getBatchSize();
		d_totalRecProcessed=batch.getTotalRecProcessed();
		
		// Start of- return order number
		returnOrderNumber=ResourceProvider.getInstance().getReturnOrderNumber().longValue();
		// End of- return order number
		
		// Populate PROVINCE
		log.info("Loading POS Province.....");
		POSProvince province = new POSProvince();
		province.populateStoreProvincePairs();
				
		// Populate Left Handed Fridge SKU numbers
		log.info("Loading Left Handed SKU Numbers....");
//		leftSku2rightSku = mcfDAO.getLhfSKU();
		
		// populate furniture warranty categories
		furnitureCategories=(List) Arrays.asList(wrfeeCategories);
	}

	/**
	 * 
	 * @return
	 * @throws SOCException
	 */
	public int processRecords() throws SOCException {
		log.info("Started processing Open Orders...");
		int result = 0;
		PreparedStatement openOrderStmt=null;
		long badRecords =0;
		ResultSet rsOpenOrders=null;
		
		String fetchClosedOrdersQuery = null;
		d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(SOCConstants.MESSAGE_PROCESSING_OPEN_ORDER_STARTS));
		int ordersFetched=0;
		
		if(d_batchSize > 0) {
 			fetchClosedOrdersQuery = QueryReader.getQuery(QueryConstants.SELECT_OPEN_ORDERS_QUERY);
		}
		else {
			fetchClosedOrdersQuery = QueryReader.getQuery(QueryConstants.SELECT_ALL_OPEN_ORDERS_QUERY);
		}

		try  {
			openOrderStmt= provider.getdbConnection().prepareStatement(fetchClosedOrdersQuery);
			// Change this line when testng to create xml for particular record
			//d_totalRecProcessed=29;					
			openOrderStmt.setInt(1, d_totalRecProcessed+1);
			
			if(d_batchSize > 0) {
				openOrderStmt.setInt(2, d_totalRecProcessed+d_batchSize);			
			}
			rsOpenOrders=openOrderStmt.executeQuery();
			long orderNumber = -1;
			long lastOrderNumber = -1;
			ArrayList<COFIOrderLine> orderLines = new ArrayList<COFIOrderLine>();	
			
			while(rsOpenOrders.next()) {
				COFIOrderLine closedOrderLine=getOrderLine(rsOpenOrders);	
				boolean badRecord=false;				
				orderNumber =closedOrderLine.getOrderNumber();
				
				if(lastOrderNumber!=-1 && lastOrderNumber!=orderNumber) {
					ordersFetched++;
					log.info("processing order "+lastOrderNumber);
					processOrder(orderLines,lastOrderNumber);
					orderLines = new ArrayList<COFIOrderLine>();
				}
				if(!orderLines.contains(closedOrderLine)) {
					orderLines.add(closedOrderLine);
				}				
				lastOrderNumber=orderNumber;
			}
			
			if(orderLines.size() > 0) {
				log.info("processing order "+orderNumber);
				processOrder(orderLines,orderNumber);				
				ordersFetched++;
			}
			statisticsHandler.updateMessages();
			
			if(d_batchSize==0) {
				result=d_totalRecProcessed+ordersFetched;
			}
			else {
				result=d_totalRecProcessed+d_batchSize;
			}
			d_recordsFetched = ordersFetched;
			
			d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(SOCConstants.MESSAGE_PROCESSING_OPEN_ORDER_ENDS));
			log.info("Completed processing Open Orders...");
			return result;
		}
		catch (SQLException se)  {
			se.printStackTrace();
			d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(ErrorMessageReader.getError(
					ErrorConstants.FAILED_DATA_PROCESS_OPEN_ORDERS)+SOCConstants.NEW_LINE+se.getMessage()));
			throw new SOCException(
					ErrorMessageReader.getError(
							ErrorConstants.FAILED_DATA_PROCESS_OPEN_ORDERS),se);
		}
		finally {
			try {
				if(rsOpenOrders!=null) {
					rsOpenOrders.close();
				}
			}
			catch (SQLException sqle) {
				d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(ErrorMessageReader.getError(
						ErrorConstants.FAILED_CLOSE_RESULTSET_TBL_STAGING_OPEN_ORDER_LINES)+SOCConstants.NEW_LINE+sqle.getMessage()));
				throw new SOCException(
						ErrorMessageReader.getError(
								ErrorConstants.FAILED_CLOSE_RESULTSET_TBL_STAGING_OPEN_ORDER_LINES),sqle);
			}
			
			try {
				if(openOrderStmt!=null) {
					openOrderStmt.close();
				}
			}
			catch (SQLException sqle) {
				d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(ErrorMessageReader.getError(
						ErrorConstants.FAILED_CLOSE_STATEMENT_TBL_STAGING_OPEN_ORDER_LINES)+SOCConstants.NEW_LINE+sqle.getMessage()));
				throw new SOCException(
						ErrorMessageReader.getError(
								ErrorConstants.FAILED_CLOSE_STATEMENT_TBL_STAGING_OPEN_ORDER_LINES),sqle);
			}			
		}
	}	
	
	/**
	 * 
	 * @param rs
	 * @return
	 * @throws SOCException
	 */
	private COFIOrderLine getOrderLine(ResultSet rs) throws SOCException {
		COFIOrderLine orderLine = new COFIOrderLine();
		long orderNum = -1;
		try {
			orderLine.setSerialNumber(rs.getInt(SERIAL_NUMBER));
			orderLine.setHeaderID(rs.getInt(HEADER_ID));
			
			orderNum = rs.getLong(ORDER_NUMBER);
			orderLine.setOrderNumber(orderNum);
			
			orderLine.setOrderDate(rs.getTimestamp(ORDERED_DATE));
			orderLine.setPartyId(rs.getString(PARTY_ID));
			orderLine.setLineId(rs.getLong(LINE_ID));
			orderLine.setLineTypeId(rs.getInt(LINE_TYPE_ID));
			orderLine.setLineNumber(rs.getInt(LINE_NUMBER));
			orderLine.setLineCategoryCode(rs.getString(LINE_CATEGORY_CODE));
			orderLine.setHeaderBillToKey(rs.getLong(HEADER_BILL_TO_KEY));
			orderLine.setHeaderShipToKey(rs.getLong(HEADER_SHIP_TO_KEY));		
			orderLine.setLineBillToKey(rs.getLong(LINE_BILL_TO_KEY));
			orderLine.setLineShipToKey(rs.getLong(LINE_SHIP_TO_KEY));		
			orderLine.setHeaderAttribute3(rs.getString(HEADER_ATTRIB3));
			orderLine.setHeaderAttribute5(rs.getString(HEADER_ATTRIB5));
			orderLine.setEmpBatchNum(rs.getString(EMP_BADGE_NUM));
			orderLine.setTaxExemptType(rs.getString(TAX_EXEMPT_TYPE));
			orderLine.setTaxExemptCertificate(rs.getString(TAX_EXEMPT_CERT));
			orderLine.setHeaderInvoiceToOrgId(rs.getInt(HEADER_INVOICE_TO_ORG_ID));
			orderLine.setHeaderShipToOrgId(rs.getInt(HEADER_SHIP_TO_ORG_ID));
			orderLine.setOrgCode(rs.getInt(ORG_CODE));
			orderLine.setShipNode(rs.getInt(SHIP_NODE));
			orderLine.setUnitSellingPrice(rs.getBigDecimal(UNIT_SELLING_PRICE));
			orderLine.setUnitListPrice(rs.getBigDecimal(UNIT_LIST_PRICE));
			orderLine.setOrderedQuantity(rs.getInt(ORDERED_QUANTITY));
			orderLine.setScheduleShipDate(rs.getTimestamp(SCHEDULE_SHIP_DATE));
			orderLine.setPromiseDate(rs.getTimestamp(PROMISE_DATE));
			orderLine.setShippingMethodCode(rs.getString(SHIPPING_METHOD_CODE));
			orderLine.setLinesShipFromOrgId(rs.getInt(LINES_SHIP_FROM_ORG_ID));
			orderLine.setLinesShipToOrgId(rs.getInt(LINES_SHIP_TO_ORG_ID));
			orderLine.setSubInventory(rs.getString(SUBINVENTORY));
			orderLine.setTaxValue(rs.getBigDecimal(TAX_VALUE));
			orderLine.setGiftRegLineNumber(rs.getString(GIFT_REG_LINE_NUM));
			orderLine.setGiftRegNumber(rs.getString(GIFT_REG_NUM));
			orderLine.setLineAttribute3(rs.getString(LINE_ATTRIB3));
			orderLine.setLineAttribute7(rs.getString(LINE_ATTRIB7));
			orderLine.setLineRetAttribute1(rs.getString(LINE_RET_ATTRIB1));
			orderLine.setLineRetAttribute2(rs.getLong(LINE_RET_ATTRIB2));
			orderLine.setLineRetAttribute3(rs.getString(LINE_RET_ATTRIB3));
			orderLine.setLineRetAttribute4(rs.getLong(LINE_RET_ATTRIB4));
			orderLine.setLineRetAttribute5(rs.getLong(LINE_RET_ATTRIB5));
			orderLine.setLineStatus(rs.getString(LINE_STATUS));
			orderLine.setServiceRefLineId(rs.getInt(SERVICE_REF_LINE_ID));
			orderLine.setInventoryItemId(rs.getInt(INVENTORY_ITEM_ID));
			orderLine.setUnitWeight(rs.getBigDecimal(UNIT_WEIGHT));
			orderLine.setWeightUOMCode(rs.getString(WEIGHT_UOM_CODE));
			orderLine.setItemSKU(rs.getString(ITEM_SKU));
			orderLine.setItemType(rs.getString(ITEM_TYPE));
			orderLine.setItemDescription(rs.getString(ITEM_DESCRIPTION));
			orderLine.setItemCatalogGroupId(rs.getString(ITEM_CATALOG_GROUP_ID));
			orderLine.setItemCategory(rs.getString(ITEM_CATEGORY));
			orderLine.setPrimaryUnitOfMeasure(rs.getString(PRIMARY_UNIT_OF_MEASURE));
			orderLine.setLocationId(rs.getInt(LOCATION_ID));
			orderLine.setSwingByStore(rs.getString(SWINGBYSTORE));
			orderLine.setCashReceiptId(rs.getInt(CASH_RECEIPT_ID));
			orderLine.setReceiptDate(rs.getTimestamp(RECEIPT_DATE));
			orderLine.setPosTxnNo(rs.getString(POSTXNNO));
			orderLine.setPosRegNo(rs.getString(POSREGNO));
			orderLine.setPosStoreNo(rs.getString(POSSTORENO));
			orderLine.setTaxProvince(rs.getString(TAX_PROVINCE));
			orderLine.setGstTax(rs.getBigDecimal(GSTTAX));
			orderLine.setGstPercent(rs.getBigDecimal(GSTPERCENT));
			orderLine.setPstTax(rs.getBigDecimal(PSTTAX));
			orderLine.setPstPercent(rs.getBigDecimal(PSTPERCENT));
			orderLine.setHstTax(rs.getBigDecimal(HSTTAX));
			orderLine.setHstPercent(rs.getBigDecimal(HSTPERCENT));
			orderLine.setReleaseStatus(rs.getString(RELEASED_STATUS));
			orderLine.setQuantityShipped(rs.getInt(QUANTITY_SHIPPED));
			orderLine.setQuantityReceived(rs.getInt(QUANTITY_RECEIVED));		
		}
		catch (SQLException sqle) {
			sqle.printStackTrace();
			d_fileWriter.write(d_logFileName, SOCUtility.writeLogMessage(ErrorMessageReader.getError(
					ErrorConstants.FAILED_RECORD_PROCESS_TBL_STAGING_OPEN_ORDER_LINES)+orderNum+SOCConstants.NEW_LINE+sqle.getMessage()));
			throw new SOCException(
					ErrorMessageReader.getError(
							ErrorConstants.FAILED_RECORD_PROCESS_TBL_STAGING_OPEN_ORDER_LINES) + orderNum ,sqle);
		}
		return orderLine;
	}
		
	/**
	 * 
	 * @param orderLines
	 * @param orderNumber
	 * @throws SOCException
	 */
	private void processOrder(ArrayList<COFIOrderLine> orderLines,long orderNumber) throws SOCException {
		ArrayList<COFIOrderLine> closedLineAdjustmentLines = new ArrayList<COFIOrderLine>();
		ArrayList<COFIOrderLine> returnLines = new ArrayList<COFIOrderLine>();
		HashMap<Long,COFIOrderLine> salesLinesMap = new HashMap<Long,COFIOrderLine>();
		
		if(orderLines != null && orderLines.size() > 0) {
			log.info("-----------------------------------");
			log.info("COFI Order Lines");
			log.info("-----------------------------------");
			
			Iterator<COFIOrderLine> iter=orderLines.iterator();
    		while(iter.hasNext()) {
    			COFIOrderLine line = iter.next();
    			String lineStatus = line.getLineStatus();
    			
    			if (SOCConstants.LINE_TYPE_DEL.equals(line.getItemType())) {
    				line.setDeliveryLineExists(true);
    			}
    			
    			// [Filter 1] do not consider CANCELLED lines
    			if (lineStatus != null && !"CANCELLED".equals(lineStatus)) {     			
	    			int lineTypeId = line.getLineTypeId();
	    			if(lineTypeId==1006 || lineTypeId==1007) {
	    				log.info("[Return Line] " + line);
	    				line.setReturnLine(true);
	    				returnLines.add(line);
	    			}
	    			else if(lineTypeId==1005) {
	    				if(line.getLineRetAttribute5()!=null) {
	    					log.info("[Closed Line Adjustments] " + line);
	    					closedLineAdjustmentLines.add(line);
	    				}
	    				else if(line.getLineRetAttribute4()!=null || line.getLineRetAttribute2()!=null ) {
	    					log.info("[Return Line] " + line);
	    					line.setReturnLine(true);
	    					if (!returnLines.contains(line)) {
	    						returnLines.add(line);
	    					}
	    				}
	    				else {
	    					log.info("[Sale Line] " + line);
	    					salesLinesMap.put(line.getLineId(),line);
	    				}
	    			}
	    			else {
	    				log.info("[Sale Line] " + line);
	    				salesLinesMap.put(line.getLineId(),line);
	    			}
    			}
    			else {
    				notConvertedOrdersList.add(line.getOrderNumber());
    				log.info("[Do not Convert] Cancelled Line \n" + line);
    			}
			}    		    		
		}
				
		OpenSalesOrderDefinition orderDef = null;
		
		// Sale Orders
		if(salesLinesMap.size() > 0) {
			associateClosedLinePriceAdjustments(orderNumber,salesLinesMap,closedLineAdjustmentLines);
			associateReturnLines(orderNumber,salesLinesMap,returnLines);			
			orderDef = createOpenSaleOrderDefinition(salesLinesMap);
			log.info("Number of Sale Lines =  " + salesLinesMap.size());		
			if(orderDef != null) {
				writeDefinitionToXML(orderDef);
				convertedOrdersList.add(Long.parseLong(orderDef.getOrderNo()));
				xmlList.add(orderDef);
			}
		}
		else {
			statisticsHandler.addMessages(orderNumber, d_batchNum, SOCConstants.INFO, SOCConstants.MESSAGE_PROCESSING_CLOSED_ORDER_WITH_NO_SALES_LINE,"");
			notConvertedOrdersList.add(orderNumber);
			d_ordersNotConverted++;
		}
		
		// Return Orders
		if (returnLines.size() > 0) {    			
			filterReturnLines(returnLines);

			Iterator<COFIOrderLine> itr = returnLines.iterator();
			log.info("Number of Return Lines =  " + returnLines.size());					
			while (itr.hasNext()) {
				COFIOrderLine returnLine = itr.next();
				if ("CLOSED".equals(returnLine.getLineStatus())) {
					log.info("Eliminating CLOSED return lines " + returnLine);
					notConvertedOrdersList.add(returnLine.getOrderNumber());
				} else {
	    			orderDef = createOpenReturnOrderDefinition(returnLine);
	    			if (orderDef != null) {
    					writeDefinitionToXML(orderDef);
    					convertedOrdersList.add(Long.parseLong(orderDef.getOrderNo()));
    					xmlList.add(orderDef);
	    			}
				}
			}
		}
		
		// Exchange Orders
		if (exchangeLines.size() > 0) {
			Iterator<COFIOrderLine> itr = exchangeLines.iterator();
			log.info("Number of Exchange Lines =  " + exchangeLines.size());					
			orderDef = createOpenExchangeOrderDefinition(exchangeLines);
			if (orderDef != null) {
				writeDefinitionToXML(orderDef);
				convertedOrdersList.add(Long.parseLong(orderDef.getOrderNo()));
				xmlList.add(orderDef);			
			}
			exchangeLines = new ArrayList<COFIOrderLine>();
		}
		
		batch.setXmlList(xmlList);
	}

	/**
	 * Writes an OpenSalesOrderDefinition to an XML File
	 * 
	 * @param orderDef
	 */
	public void writeDefinitionToXML(OpenSalesOrderDefinition orderDef) 
	throws SOCException {
		OpenSalesOrderDefinitionMarshaller marshaller = OpenSalesOrderDefinitionMarshaller.getInstance();
		Document document = null;
		try {
			marshaller.createOrderDefinitionWriter(orderDef);
			document = marshaller.writeOrderDefinition(orderDef);
			
			// create a child director for storing xml files limited to batch size
			int childDir = getChildDirectory();
			File childDirRef= new File(batch.getXmlOutputDirectory() + SOCConstants.DELIMITER + childDir);
	    	if (!childDirRef.exists()) {
	    		childDirRef.mkdir();    	
	    	}
			
			String fileName = childDirRef.getAbsolutePath() + SOCConstants.DELIMITER + 
								orderDef.getOrderName() + "_" + orderDef.getOrderNo() + ".xml";
			log.info("Writing " + fileName);
			SOCUtility.writeXmlFile(document, fileName);		
			d_xmlCounter++;
			document = null;
			orderDef = null;
		} catch (MarshallingException e) {
			throw new SOCException("Error in writing XML file.", e);
		}
	}
	
    private int getChildDirectory() {
    	int result = 0;
    	int division = ((d_xmlCounter+1)/SOCConstants.MAXIMUM_FILE_COUNT);
    	int reminder = ((d_xmlCounter+1)%SOCConstants.MAXIMUM_FILE_COUNT);
    	
    	if(reminder > 0) {
    		result = division + 1;
    	}
    	else {
    		result = division;
    	}
    	
    	return result;
    }
			
	private void filterSalesLines(HashMap<Long,COFIOrderLine> salesLinesMap) {
		Iterator itr = salesLinesMap.values().iterator();
		while(itr.hasNext()) {
			COFIOrderLine line = (COFIOrderLine)itr.next();			
		}
	}	
	
	private void filterReturnLines(ArrayList<COFIOrderLine> returnLines) {
		Iterator iterator = returnLines.iterator();
		while (iterator.hasNext()) {
			COFIOrderLine line = (COFIOrderLine)iterator.next();			
		}
	}	
	
	/**
	 * Convert the ClosedLinePriceAdjustments.
	 * 
	 * @param orderNum
	 * @param salesLinesMap
	 * @param closedLineAdjustmentLines
	 * @throws SOCException
	 */
	private void associateClosedLinePriceAdjustments(long orderNum, 
			HashMap<Long,COFIOrderLine> salesLinesMap, 
			ArrayList<COFIOrderLine> closedLineAdjustmentLines) throws SOCException {
		
		Iterator<COFIOrderLine> iter=closedLineAdjustmentLines.iterator();
		COFIOrderLine closedLinePriceAdjustment = null;
		log.info("-----------------------------------");		
		log.info("Creating Associations Sale->ClosedLinePriceAdjustments");
		log.info("-----------------------------------");		
		while(iter.hasNext()) {
			closedLinePriceAdjustment = iter.next();
log.info("[Assoc]Closed Line PriceAdjustments: " + closedLinePriceAdjustment);			
			BigDecimal priceAdjt =  closedLinePriceAdjustment.getUnitSellingPrice();
			
			COFIOrderLine salesLine = salesLinesMap.get(closedLinePriceAdjustment.getLineRetAttribute5());
log.info("[Assoc]Closed Line PriceAdjustments - Corresponding Sales Line: " + salesLine);
			if(salesLine!=null) {
				BigDecimal origPrice =salesLine.getUnitSellingPrice();
				BigDecimal adjustedPrice = SOCUtility.getDifference(origPrice,priceAdjt);
				
				BigDecimal priceAdjtTaxValue = closedLinePriceAdjustment.getTaxValue();
				BigDecimal origTaxValue = salesLine.getTaxValue();			
				BigDecimal adjustedTaxValue = SOCUtility.getDifference(origTaxValue,priceAdjtTaxValue);
				
				BigDecimal priceAdjtGstTax = (closedLinePriceAdjustment.getGstTax() == null) ? new BigDecimal("0") : closedLinePriceAdjustment.getGstTax();
				BigDecimal origGstTax = (salesLine.getGstTax() == null) ? new BigDecimal("0") : salesLine.getGstTax();
				BigDecimal adjustedGstTax  = SOCUtility.getDifference(origGstTax,priceAdjtGstTax);
				
				BigDecimal priceAdjtPstTax = (closedLinePriceAdjustment.getPstTax() == null) ? new BigDecimal("0") : closedLinePriceAdjustment.getPstTax();
				BigDecimal origPstTax =(salesLine.getPstTax() == null) ? new BigDecimal("0") : salesLine.getPstTax();
				BigDecimal adjustedPstTax = SOCUtility.getDifference(origPstTax,priceAdjtPstTax);
				
				BigDecimal priceAdjtHstTax =(closedLinePriceAdjustment.getHstTax() == null) ? new BigDecimal("0") : closedLinePriceAdjustment.getHstTax();
				BigDecimal origHstTax = (salesLine.getHstTax() == null) ? new BigDecimal("0") : salesLine.getHstTax();
				BigDecimal adjustedHstTax = SOCUtility.getDifference(origHstTax,priceAdjtHstTax);
				
				salesLine.setUnitSellingPrice(adjustedPrice);
				salesLine.setTaxValue(adjustedTaxValue);
				salesLine.setGstTax(adjustedGstTax);
				salesLine.setPstTax(adjustedPstTax);
				salesLine.setHstTax(adjustedHstTax);
			}
			else {
				statisticsHandler.addMessages(orderNum, batch.getBatchNumber(), SOCConstants.WARNING, SOCConstants.MESSAGE_PROCESSING_CLOSED_PRICE_ADJUSTMENT_WITH_NO_SALES_LINE,closedLinePriceAdjustment.getLineId().toString());
			}
    	}
	}

	/**
	 * Creates an association between a Sale Line and Return Line.
	 *  
	 * @param orderNum
	 * @param salesLinesMap
	 * @param returnLines
	 * @throws SOCException
	 */
	private void associateReturnLines(long orderNum, HashMap<Long, COFIOrderLine> salesLinesMap, 
			ArrayList<COFIOrderLine> returnLines) throws SOCException {
		
		Iterator<COFIOrderLine> iter=returnLines.iterator();
		COFIOrderLine returnLine = null;
		COFIOrderLine salesLine  = null;
		boolean saleLineFound= false;
log.info("-----------------------------------");		
log.info("Creating Associations Sale->Return");
log.info("-----------------------------------");
		while(iter.hasNext()) {
			returnLine = iter.next();						
			Long returnAttr2=returnLine.getLineRetAttribute2();
			Long returnAttr4=returnLine.getLineRetAttribute4();
			if(returnAttr2!=null) {
				salesLine= salesLinesMap.get(returnAttr2);
log.info("[Assoc]Sale Line   --> " + salesLine);
log.info("[Assoc]Return Line <-- " + returnLine);
			}
			else if(returnAttr4!=null) {
				salesLine= salesLinesMap.get(returnAttr4);
log.info("[Assoc]Sale Line   --> " + salesLine);
log.info("[Assoc]Return Line <-- " + returnLine);				
			}
			if(salesLine!=null) {
				// [Filter 2] remove the CLOSED sale and it's respective CLOSED return line
				if(salesLine.getLineStatus().equals(returnLine.getLineStatus())) {
					salesLinesMap.remove(salesLine.getLineId()); 
					salesLinesMap.remove(salesLine.getLineId());
					notConvertedOrdersList.add(salesLine.getOrderNumber());
					notConvertedOrdersList.add(returnLine.getOrderNumber());
log.info("[Assoc]Removing Sale line " + salesLine);
log.info("[Assoc]Removing Return line " + returnLine);
					saleLineFound = true;
				} 
				else if(!(returnLine.getLineStatus().equals("CANCELLED"))&& !(returnLine.getLineStatus().equals("CLOSED")))
				{
					
					Iterator iter1 = salesLinesMap.values().iterator();
					while(iter1.hasNext())
					{
						COFIOrderLine line1=(COFIOrderLine)iter1.next();
						if(!line1.getLineStatus().equals("CLOSED") && !line1.getLineStatus().equals("CANCELLED"))
						{
							if(!exchangeLines.contains(line1))
							{
								
								iter1.remove();
								exchangeLines.add(line1);
								log.info("Exchange Line: " + line1);	
								
							}
						}
					}
					

					
				}				
			}	
			if(saleLineFound) {
log.info("[Assoc]Corresponding Sales Line: " + salesLine);				
				salesLine.setReturned(true);
				salesLine.setReturnLine(returnLine);
			}
			else {
log.info("[Assoc]No Corresponding Return Line for Sale Line " + returnLine);
				convertedOrdersList.add(returnLine.getOrderNumber());
				if(!"CANCELLED".equals(returnLine.getLineStatus())) {
					statisticsHandler.addMessages(orderNum, batch.getBatchNumber(), SOCConstants.WARNING, SOCConstants.MESSAGE_PROCESSING_RETURN_LINE_WITH_NO_SALES_LINE, returnLine.getLineId().toString());
				}
			}
			saleLineFound= false;
    	}
	}
		
	/**
	 * Create an open sale order definition.
	 * 
	 * @param lineInfo
	 * @return
	 */
	public OpenSalesOrderDefinition createOpenSaleOrderDefinition(HashMap<Long,COFIOrderLine> salesLinesMap) 
	throws SOCException {	
		OpenSalesOrderDefinition result = new OpenSalesOrderDefinition();		
		COFIOrderLine lineInfo = new COFIOrderLine();						
		log.info("-----------------------------------");		
		log.info("Creating Sale Order");
		log.info("-----------------------------------");
		
		if (lineInfo != null) {									
			Iterator<COFIOrderLine> iterator = salesLinesMap.values().iterator();			
			while (iterator.hasNext()) {
				lineInfo = (COFIOrderLine) iterator.next();	
				// Order
				createOrderAttributes(result, lineInfo);
				createOrderLine(result, lineInfo,false);
				
//				System.out.println(lineInfo.getItemType());			
//				if (SOCConstants.LINE_TYPE_WTY.equals(lineInfo.getItemType())) {
//					// OrderLineRelationships
//					createOrderLineRelationShips(result, lineInfo);						
//				}
			}		
			
			setExtnWarrantySKU(result);	
			createOrderLineRelationShips(result, lineInfo);						
			
			
			// No need to create header taxes at the moment, may be in future
			// HeaderTaxes
			// createHeaderTaxes(result, lineInfo);

			// No need to create this at this moment, may be in future
			// ProductServiceAssocs
			// createProductServiceAssocs(result, lineInfo);
						
			log.info(result);
		}
		
		return result;
	}	
	
	/**
	 * Creates an open return order definition.
	 * 
	 * @param returnLines
	 * @return
	 */
	public OpenSalesOrderDefinition createOpenReturnOrderDefinition(COFIOrderLine returnLine) 
	throws SOCException {		
		OpenSalesOrderDefinition result = new OpenSalesOrderDefinition();							
		log.info("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");		
		log.info("Creating Return Order");
		log.info("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");		
		if (returnLine != null) {										
			// Order
			createOrderAttributes(result, returnLine);
			primeLineNo = 0;
			olrParentPrimeLineNo = 0;
			olfChildPrimeLineNo = 0;
			psaProductPrimeLineNo = 0;
			psaServicePrimeLineNo = 0;
			createOrderLine(result, returnLine,false);
					
			// No need to create header taxes at the moment, may be in future
			// HeaderTaxes
			// createHeaderTaxes(result, lineInfo);
			
			// No need to create this at this moment, may be in future
			// ProductServiceAssocs
			// createProductServiceAssocs(result, lineInfo);
			
			// OrderLineRelationships
			//createOrderLineRelationShips(result, returnLine);
			
			associateUsageFee(result);
		}
		return result;
	}
	
	/**
	 * Creates an open exchange order definition.
	 * 
	 * @param returnLines
	 * @return
	 */
	public OpenSalesOrderDefinition createOpenExchangeOrderDefinition(ArrayList<COFIOrderLine> exLine) 
	throws SOCException {
		
		int serialNo=0;
		boolean isExchangeExist=false;
		OpenSalesOrderDefinition result = new OpenSalesOrderDefinition();
		COFIOrderLine lineInfo = new COFIOrderLine();
		if (lineInfo != null) 
		{									
			Iterator<COFIOrderLine> iterator = exLine.iterator();
			
			log.info("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");		
			log.info("Creating Exchange Order");
			log.info("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
			
		
			while (iterator.hasNext()) 
			{
				lineInfo = (COFIOrderLine) iterator.next();	
				// Order
				serialNo=lineInfo.getSerialNumber();
				createExchangeOrderAttributes(result, lineInfo);
				primeLineNo = 0;
				olrParentPrimeLineNo = 0;
				olfChildPrimeLineNo = 0;
				psaProductPrimeLineNo = 0;
				psaServicePrimeLineNo = 0;
				createOrderLine(result, lineInfo,true);
				isExchangeExist=true;
			}
			if(isExchangeExist)
			{
				result.setOrderName("openExchangeOrder_" +serialNo );
		
				randNum=(rand.nextInt(99));
				if (randNum<10)
				{
					retOrdNum=String.valueOf(returnOrderNumber)+"0"+randNum ;
				}
				else
				{
					retOrdNum=String.valueOf(returnOrderNumber)+randNum ;
				}
				result.setOrderNo(retOrdNum);
				log.info("Creating Exchange order:"+retOrdNum);
				returnOrderNumber = returnOrderNumber + 1;
				isExchangeExist=false;
			}
			setExtnWarrantySKU(result);	
			createOrderLineRelationShips(result, lineInfo);						
			
			
		}
		return result;
	}

	/**
	 * Setting the values for order attributes.
	 * 
	 * @param result
	 * @param lineInfo
	 */
	public void createOrderAttributes(OpenSalesOrderDefinition result, COFIOrderLine lineInfo) {
		result.setBillToID(lineInfo.getPartyId());
		result.setBillToKey(""+lineInfo.getHeaderBillToKey());
		
		if (lineInfo.isReturnLine()) {
			result.setDocumentType("0003");
			result.setOrderName("openReturnOrder_" + lineInfo.getSerialNumber());		
			randNum=(rand.nextInt(99));
			if (randNum<10)
			{
				retOrdNum=String.valueOf(returnOrderNumber)+"0"+randNum ;
			}
			else
			{
				retOrdNum=String.valueOf(returnOrderNumber)+randNum ;
			}
			result.setOrderNo(retOrdNum);
			returnOrderNumber = returnOrderNumber + 1;	 			
		} else {	
			result.setDocumentType("0001");
			result.setOrderNo(""+lineInfo.getOrderNumber());
			String orderName =  "openSalesOrder_"; 
			result.setOrderName( orderName + lineInfo.getSerialNumber());
		}
		
		result.setEnterpriseCode("BAY");
		result.setEntryType("Store");
		result.setOrderDate(SOCUtility.formatDate(lineInfo.getOrderDate()));				
		result.setPaymentStatus(""); // default value is EMPTY
		result.setSellerOrganizationCode(""+lineInfo.getOrgCode());
		result.setShipToID(lineInfo.getPartyId());
		
		if (lineInfo.isDeliveryLineExists()) {
			result.setShipToKey(lineInfo.getHeaderShipToKey().toString());
		}
				
		result.setTaxExemptFlag((lineInfo.getTaxExemptType() == null) ? "N" : "Y");
		result.setTaxExemptCertificate(lineInfo.getTaxExemptCertificate());
		
		createOrderExtension(result, lineInfo);
	}	
	
	/**
	 * Setting the values for  Exchange order attributes.
	 * 
	 * @param result
	 * @param lineInfo
	 */
	public void createExchangeOrderAttributes(OpenSalesOrderDefinition result, COFIOrderLine lineInfo) {
		result.setBillToID(lineInfo.getPartyId());
		result.setBillToKey(""+lineInfo.getHeaderInvoiceToOrgId());
		result.setDocumentType("0003");
		result.setEnterpriseCode("BAY");
		result.setEntryType("Store");
		result.setOrderDate(SOCUtility.formatDate(lineInfo.getOrderDate()));				
		result.setPaymentStatus(""); // changed from "NOT_APPLICABLE" to EMPTY as per Ramana
		result.setSellerOrganizationCode(""+lineInfo.getOrgCode());
		result.setShipToID(lineInfo.getPartyId());
		result.setShipToKey(""+lineInfo.getHeaderShipToOrgId());
		result.setTaxExemptFlag((lineInfo.getTaxExemptType() == null) ? "N" : "Y");
		result.setTaxExemptCertificate(lineInfo.getTaxExemptCertificate());
		
		createOrderExtension(result, lineInfo);
	}
	
	/**
	 * Creates an Extension for an Order
	 * 
	 * @param result
	 * @param lineInfo
	 */
	public void createOrderExtension(OpenSalesOrderDefinition result, COFIOrderLine lineInfo) {
		// Extn
		OrderExtension extn = new OrderExtension();
		String depositAmount = MCFConverter.getExtnDeposit(lineInfo.getHeaderAttribute3(), lineInfo.getHeaderAttribute5(), 2);
		extn.setExtnIsDepositAmountCollected(MCFConverter.getExtnDeposit(lineInfo.getHeaderAttribute3(), lineInfo.getHeaderAttribute5(), 1));
		extn.setExtnDepositAmount(depositAmount);
		extn.setExtnDepositFlag(Float.parseFloat(depositAmount) > 0 ? "Y" : "N");
		extn.setExtnGiftRegistryNum(lineInfo.getGiftRegNumber());
		extn.setExtnHBCAssociateID(lineInfo.getEmpBatchNum());
		extn.setExtnAmountCollected(MCFConverter.getHeaderChargeTotal(result).toString());
		result.setOrderExtn(extn);
	}
			
	/**
	 * Creates an OrderLineRelationships
	 * 
	 * @param orderDef
	 * @param line
	 */
	public void createOrderLineRelationShips(OpenSalesOrderDefinition orderDef, COFIOrderLine line) {
		
		log.info("-----------------------------------");		
		log.info("Creating OrderLineRelationships");
		log.info("-----------------------------------");

		// OrderLineRelationShips
		
		
//log.debug(primeLineNoMap);
//log.debug(primeLineNoMap.containsKey(line));
//		
//		ParentLine parentLine = new ParentLine();
//		olrParentPrimeLineNo++;
//		parentLine.setPrimeLineNo(""+olrParentPrimeLineNo);			 		
//		parentLine.setSubLineNo("1");
//		orderLineRelationShip.setParentLine(parentLine);
//		
//		ChildLine childLine = new ChildLine();
//		childLine.setSubLineNo("1");
//		childLine.setPrimeLineNo(""+olfChildPrimeLineNo);
//		orderLineRelationShip.setChildLine(childLine);			
//		orderDef.addOrderLineRelationShip(orderLineRelationShip);
		
		ChildLine childLine = new ChildLine();

				
		if(orderDef.getWFREELinesList() != null && orderDef.getWFREELinesList().size() > 0) {
			log.info("WRFEE line exists...");
			
			OrderLine wrfeeLine = orderDef.getWFREELinesList().get(0);
			String primeNo=wrfeeLine.getPrimeLineNo();
			if(primeNo!=null && (!primeNo.equals(""))) {
				childLine.setSubLineNo("1");
				childLine.setPrimeLineNo(primeNo);
							
			}
			
		}
		
		
		if(orderDef.getFunitureWtyLinesList() != null && orderDef.getFunitureWtyLinesList().size() > 0) {
			log.info("Furniture WTY line exists...");
			Iterator<OrderLine> iterFurniture= orderDef.getFunitureWtyLinesList().iterator();
			while(iterFurniture.hasNext()) {				
				OrderLine orderLine = iterFurniture.next();
				ParentLine parentLine1 = new ParentLine();
				OrderLineRelationShip orderLineRelationShip = new OrderLineRelationShip();
				orderLineRelationShip.setRelationShipType("ACCESSORIES");
				String serviceRefLineId = orderLine.getServiceRefLineId();
						
				if(serviceRefLineId!=null) {
					OrderLine itemLine = getLinesMap().get(serviceRefLineId);
					if(itemLine!=null) {
						
						String primeNo=itemLine.getPrimeLineNo();
						if(primeNo!=null && (!primeNo.equals(""))) {
							parentLine1.setSubLineNo("1");
							parentLine1.setPrimeLineNo(primeNo);
							orderLineRelationShip.setParentLine(parentLine1);
							orderLineRelationShip.setChildLine(childLine);			
							orderDef.addOrderLineRelationShip(orderLineRelationShip);
							
						}
					} else {
						log.info("OrderLine is null for " + serviceRefLineId + ", cannot set order line relationships");
					}
				} else {
					log.info("serviceRefLineId is null, cannot set order line relationships");
				}
			}
		}

		if(orderDef.getNonFunitureWtyLinesList() != null && orderDef.getNonFunitureWtyLinesList().size() > 0) {
log.info("Non Furniture WTY line exists...");			
			Iterator<OrderLine> iterNonFurniture = orderDef.getNonFunitureWtyLinesList().iterator();
			while(iterNonFurniture.hasNext()) {
				OrderLine orderLine = iterNonFurniture.next();
				ParentLine parentLine1 = new ParentLine();
				OrderLineRelationShip orderLineRelationShip = new OrderLineRelationShip();
				orderLineRelationShip.setRelationShipType("ACCESSORIES");				
				ChildLine childLine1 = new ChildLine();
				String serviceRefLineId = orderLine.getServiceRefLineId();
				
				if(serviceRefLineId!=null) {
					OrderLine itemLine = getLinesMap().get(serviceRefLineId);					
					if(itemLine!=null) {
						String primeNo=itemLine.getPrimeLineNo();
						if(primeNo!=null && (!primeNo.equals(""))) {
							parentLine1.setSubLineNo("1");
						    parentLine1.setPrimeLineNo(primeNo);
							orderLineRelationShip.setParentLine(parentLine1);
							
							}
						
						}
						String primeNo=orderLine.getPrimeLineNo();
						if(primeNo!=null && (!primeNo.equals(""))) {
							childLine1.setSubLineNo("1");
							childLine1.setPrimeLineNo(primeNo);
							orderLineRelationShip.setChildLine(childLine1);			
							orderDef.addOrderLineRelationShip(orderLineRelationShip);
						}
						
					}
				}
			}
		
		
	}		
	
	/**
	 * Creates a ProductServiceAssocs.
	 * 
	 * @param orderDef
	 * @param line
	 */
	public void createProductServiceAssocs(OpenSalesOrderDefinition orderDef, COFIOrderLine line) {
		
		log.info("-----------------------------------");		
		log.info("Creating ProductServiceAssocs");
		log.info("-----------------------------------");

		// ProductServiceAssocs
		ProductServiceAssoc productServiceAssoc = new ProductServiceAssoc();
		productServiceAssoc.setProductLineAttr("");					
		ProductLine productLine = new ProductLine();
		psaProductPrimeLineNo++;
		productLine.setPrimeLineNo(""+psaProductPrimeLineNo);
		productLine.setSubLineNo("1");
		productServiceAssoc.setProductLine(productLine);
		
		ServiceLine serviceLine =  new ServiceLine();
		psaServicePrimeLineNo++;
		serviceLine.setPrimeLineNo(""+psaServicePrimeLineNo);
		serviceLine.setSubLineNo("1");			
		productServiceAssoc.setServiceLine(serviceLine);
		orderDef.addProductServiceAssoc(productServiceAssoc);		
	}
	
	/**
	 * Creates a HeaderTaxes.
	 * 
	 * @param orderDef
	 * @param line
	 */
	public void createHeaderTaxes(OpenSalesOrderDefinition orderDef, COFIOrderLine line) {
		log.info("-----------------------------------");		
		log.info("Creating HeaderTaxes");
		log.info("-----------------------------------");

		HeaderTax headerTax = new HeaderTax();
		headerTax.setTax(new BigDecimal("0.00"));
		headerTax.setTaxableFlag("");
		headerTax.setTaxName("");
		headerTax.setTaxPercentage("");
		orderDef.addHeaderTax(headerTax);					
	}

	/**
	 * Creates a HeaderCharges
	 * @TODO Calculate the ChargeAmount
	 * 
	 * @param orderDef
	 * @param line
	 * @throws SQLException
	 */
	public void createHeaderCharges(OpenSalesOrderDefinition orderDef, COFIOrderLine line) 
	throws SOCException {			
		HashMap<String, Charge> sku2charge = mcfDAO.getChargeInfo();		
		Charge chargeInfo = sku2charge.get(line.getItemSKU());		
		log.info(chargeInfo);	
		if (chargeInfo != null) {
			HeaderCharge headerCharge = new HeaderCharge();
			BigDecimal quantity = new BigDecimal(line.getOrderedQuantity());
			headerCharge.setChargeAmount(line.getUnitSellingPrice().multiply(quantity).setScale(2)); // clarification
			headerCharge.setChargeCategory(chargeInfo.getGroup() == null ? "" : chargeInfo.getGroup());
			headerCharge.setChargeName(chargeInfo.getName() == null ?  "" : chargeInfo.getName());
			orderDef.addHeaderCharge(headerCharge);
		}
		else {
			log.info("Cannot create header charges for " + line.getItemSKU());
		}
	}
	
	/**
	 * Creates an OrderLine
	 * 
	 * @param orderLine
	 * @param line
	 * @throws SQLException
	 */
	public void createOrderLine(OpenSalesOrderDefinition orderDef, COFIOrderLine line,Boolean isExchange) 
	throws SOCException {
		
		OrderLine orderLine = new OrderLine();
		
		BigDecimal unitListPrice = line.getUnitListPrice();
		String serviceRefLineId = line.getServiceRefLineId().toString();
		orderLine.setServiceRefLineId(serviceRefLineId);		
		
		if (line.getItemType() != null) {
		
			if(SOCConstants.ALL.equals(line.getItemType())) { // Header Charges
				log.info("-----------------------------------");		
				log.info("Creating HeaderCharges");
				log.info("-----------------------------------");
	
				createHeaderCharges(orderDef, line);
				
			} else if(SOCConstants.LINE_TYPE_SALVAGE.equals(line.getItemType())) { // Line Options
				log.info("-----------------------------------");		
				log.info("Creating OrderLineOption for " + line.getItemType());
				log.info(line);		
				log.info("-----------------------------------");
				
				SalvageLine sLine = new SalvageLine();
				createSalvageLine(sLine, line);
				orderDef.addSalvageLine(sLine);
				
			} else if(((SOCConstants.LINE_TYPE_USE.equals(line.getItemType()) && line.isReturnLine())||
						SOCConstants.LINE_TYPE_EFEE.equals(line.getItemType()))) { // Line Charges
	
				log.info("-----------------------------------");		
				log.info("Creating LineCharge for " + line.getItemType());
				log.info(line);		
				log.info("-----------------------------------");
				
				// createLineChargeInfo
				createLineCharge(orderLine, line);
			} 
//			else if (SOCConstants.LINE_TYPE_WTY.equals(line.getItemType()) || 
//						SOCConstants.LINE_TYPE_WRFEE.equals(line.getItemType())) {
//				
//				log.info("-----------------------------------");		
//				log.info("Handling Line " + line.getItemType());
//				log.info(line);		
//				log.info("-----------------------------------");
//
//			}
			else if(MCFConverter.isInvalidLine(line.getItemType())) { // Do not consider these lines
				log.info("-----------------------------------");		
				log.info("Invalid Line - " + line.getItemType());
				log.info(line);		
				log.info("-----------------------------------");
		
				notConvertedOrdersList.add(line.getOrderNumber());
			}
			else if(ItemType.isConversionRequired(line.getItemType())) {
				
				log.info("-----------------------------------");		
				log.info("Creating OrderLine for " + line.getItemType());
				log.info(line);		
				log.info("-----------------------------------");
				
				// OrderLine Attributes			
				String shippingMethodCode = line.getShippingMethodCode();
				if(shippingMethodCode==null) {
					shippingMethodCode=SOCConstants.DEFAULT_SHIPPING_METHOD;
				}			
	
				String deliveryMethod = DeliveryMethod.getDeliveryMethod(shippingMethodCode);
				String fulfillmentType = FulfillmentType.getFullfillmentType(shippingMethodCode);	
				String lineType = LineType.getLineType(shippingMethodCode);			
						
				if(deliveryMethod==null) {
					deliveryMethod = DeliveryMethod.getDeliveryMethod(shippingMethodCode);
				}
						
				if(fulfillmentType==null) {
					fulfillmentType = FulfillmentType.getFullfillmentType(shippingMethodCode);
				}
							
				if(lineType==null) {
					lineType = LineType.getLineType(shippingMethodCode);
				}			
	
				orderLine.setDeliveryMethod(deliveryMethod);
				orderLine.setFullfillmentType(fulfillmentType);
				orderLine.setIsPriceLocked("Y");
				orderLine.setItemGroupCode(ItemGroupCode.getItemGroupCode(line.getItemType()));
				orderLine.setItemCategory(line.getItemCategory());
				orderLine.setLineType(lineType);
				orderLine.setLineStatus(MCFConverter.getMCFLineStatus(line));
				orderLine.setOrderedQty(""+line.getOrderedQuantity());
				orderLine.setPickableFlag("Y");
				primeLineNo++;
				orderLine.setPrimeLineNo(""+primeLineNo);
				primeLineNoMap.put(orderLine, new Integer(primeLineNo));
				
				String convertedStartDate = "";
				String convertedEndDate = "";
				String reqDeliveryDate = "";
				String reqShipDate = "";
				
				String lineAttribute3 = line.getLineAttribute3();
				if (lineAttribute3 == null || lineAttribute3.equals("")) {
					lineAttribute3 = "DEFAULT";
				}
	
				if (line.getScheduleShipDate() != null) {
					convertedStartDate = SOCUtility.getDate(SOCUtility.formatDate(line.getScheduleShipDate())) + " " + PromiseStartDate.valueOf(lineAttribute3).getBeanProperty();
					convertedEndDate = SOCUtility.getDate(SOCUtility.formatDate(line.getScheduleShipDate())) + " " + PromiseEndDate.valueOf(lineAttribute3).getBeanProperty();
					reqDeliveryDate = SOCUtility.formatDate(line.getPromiseDate());
					reqShipDate = SOCUtility.formatDate(line.getScheduleShipDate());
				}
				
				orderLine.setPromisedApptStartDate(convertedStartDate);
				orderLine.setPromisedApptEndDate(convertedEndDate);							
				orderLine.setReqDeliveryDate(reqDeliveryDate);
				orderLine.setReqShipDate(reqShipDate);
				orderLine.setShipNode(""+line.getShipNode());
				
				orderLine.setShipToId(line.getPartyId());
				orderLine.setSubLineNo("1"); // default to one		
				
				if(SOCConstants.LINE_TYPE_DEL.equals(deliveryMethod)) {
					orderLine.setShipToKey(""+line.getLineShipToKey());
				}	
				
				// OrderLineExtension
				createOrderLineExtension(orderLine, line);
				
				// Add Salvage lines to a available delivery line			
				if (SOCConstants.LINE_TYPE_DEL.equals(line.getItemType())) {
					log.info("-----------------------------------");		
					log.info("Adding OrderLineOption to " + line.getItemType());								
					Iterator<SalvageLine> itr = orderDef.getSalvageLineList().iterator();
					while (itr.hasNext()) {
						SalvageLine sLine = (SalvageLine)itr.next();
						log.info(sLine);		
						// createOrderLineOption
						createOrderLineOption(orderLine, sLine);
					}
					log.info("-----------------------------------");
				}
							
				if (line.isReturnLine()|| isExchange) {	
					// DerivedFrom
					createDerivedFrom(orderDef, orderLine, line);
				}				
							
				// createItemInfo
				createItemInfo(orderLine, line);
							
				// createLinePriceInfo
				createLinePriceInfo(orderLine, line);
				
				// createLineChargeInfo
				createLineCharge(orderLine, line);
				
				// createLineTax
				createLineTax(orderLine, line);
				
				// set the amount collected
				orderLine.getOrderLineExtension().setExtnAmountCollected(MCFConverter.getChargeTotal(orderLine).toString());

				// handle WTY and WRFEE lines
				if (SOCConstants.LINE_TYPE_WTY.equals(line.getItemType())) {			
					if(serviceRefLineId != null) {
						OrderLine primeLine = linesMap.get(serviceRefLineId);
						if(primeLine!=null)
						{
							if(!furnitureCategories.contains(primeLine.getItemCategory())) {				
								orderDef.addNonFurnitureWtyLine(orderLine);
								orderDef.addOrderLine(orderLine);
								line.setNonFurnitureWTYLine(true);
								log.info("Non Furniture WTY " + orderLine);
							} else {
								orderDef.addFurnitureWtyLine(orderLine);
								line.setFurnitureWTYLine(true);
								log.info("Furniture WTY " + orderLine);						
							}
						}
						else
						{
							log.info("This Line"+line.getLineId()+" has WTY line which has no pointer to sales line - ");
						}
					} 			
				} else if (SOCConstants.LINE_TYPE_WRFEE.equals(line.getItemType())) {
					orderDef.addWFREELine(orderLine);
					orderDef.addOrderLine(orderLine);
					log.info("WRFEE " + orderLine);					
				} else {								
					orderDef.addOrderLine(orderLine);
				}	
								
				linesMap.put(line.getLineId().toString(), orderLine);
				
				if (line.isReturnLine()) {
					log.info("Adding return line in create order line...." + orderLine);
					returnLinesMap.put(line.getLineId().toString(), orderLine);
				}
			}
		}
	}
		
	/**
	 * Creates a Salvage (SVG) line.
	 * 
	 * @param sLine
	 * @param line
	 */
	public void createSalvageLine(SalvageLine sLine, COFIOrderLine line) {
    	sLine.setItemDesc(line.getItemDescription());
    	sLine.setItemID(line.getItemSKU());
    	sLine.setUnitOfMeasure(SOCConstants.MIN);
    	BigDecimal amt = line.getUnitSellingPrice().multiply(new BigDecimal(line.getOrderedQuantity())).setScale(2);
    	sLine.setUnitPrice(amt);
    	sLine.setIsReturned(line.isReturned());
    	sLine.setStatus(line.getLineStatus());
    	sLine.setLineId(""+line.getLineId());
    	sLine.setIsHSTEligible(MCFConverter.isHSTEligible(line));
		
		BigDecimal gstTax = (line.getGstTax() == null) ? new BigDecimal("0") : line.getGstTax();
		BigDecimal pstTax = (line.getPstTax() == null) ? new BigDecimal("0") : line.getPstTax();
		BigDecimal hstTax = (line.getHstTax() == null) ? new BigDecimal("0") : line.getHstTax();
			
		if(MCFConverter.isHSTEligible(line)) {
			BigDecimal taxAmt = new BigDecimal("0");
			BigDecimal taxPercentage = new BigDecimal("0");
			if(hstTax.compareTo(new BigDecimal("0"))==1) {
				taxAmt=hstTax;
				taxPercentage=line.getHstPercent();
			}
			else {
				if(gstTax.compareTo(new BigDecimal("0"))==1) {
					taxAmt = gstTax;
					taxPercentage = line.getGstPercent();
				}
				if(pstTax.compareTo(new BigDecimal("0"))==1) {
					taxAmt = taxAmt.add(pstTax);
					taxPercentage = taxPercentage.add(line.getPstPercent());
				}
			}
		
			if(taxAmt.compareTo(new BigDecimal("0"))==1) {
				sLine.setHstTaxPercentage(taxPercentage);
				sLine.setHstTax(taxAmt);
			}			
		}
		else {
			if(gstTax.compareTo(new BigDecimal("0"))==1) {
				sLine.setGstTaxPercentage(line.getGstPercent());
				sLine.setGstTax(gstTax);
			}
			
			if(pstTax.compareTo(new BigDecimal("0"))==1) {
				sLine.setPstTaxPercentage(line.getPstPercent());
				sLine.setPstTax(pstTax);
			}
			
			if(hstTax.compareTo(new BigDecimal("0"))==1) {
				sLine.setHstTaxPercentage(line.getHstPercent());
				sLine.setHstTax(hstTax);
			}
		}		
	}
	
	/**
	 * Creates an Extension for an OrderLine.
	 * @TODO Calculate the ExtnAmountCollected and Set it.
	 * @TODO Implement Logic for ExtnWarrantySKU.
	 * @TODO Implement Logic for ExtnReverseDoorHinge
	 *  
	 * @param orderLine
	 * @param line
	 */
	public void createOrderLineExtension(OrderLine orderLine, COFIOrderLine line) {

		String subinventory = line.getSubInventory();		
		String isOpenBox = "N";
		if(subinventory!=null && (SOCConstants.SUBINVENTORY_FLOOR_MODEL.equals(subinventory) ||
				SOCConstants.SUBINVENTORY_AS_IS.equals(subinventory))) {
			isOpenBox = "Y";
		}		
		OrderLineExtension lineExtn = new OrderLineExtension();
		lineExtn.setExtnAmountCollected(""); // set to EMPTY first
		lineExtn.setExtnGiftRegistryNo(line.getGiftRegNumber());
		lineExtn.setExtnGiftRegistryLineNo(line.getGiftRegLineNumber());
		lineExtn.setExtnPOSTxnNum(line.getPosTxnNo());
		lineExtn.setExtnPOSRegNum(line.getPosRegNo());
		lineExtn.setExtnPOSStoreNum(line.getPosStoreNo());

		HashMap<String,String> storeProvinceMap =POSProvince.getPOsStoreNumProvinceMap();
		if(storeProvinceMap!=null) {
//			log.debug("Store No. " + line.getPosStoreNo());
			String posProvince = storeProvinceMap.get(line.getPosStoreNo());
//			log.debug("POSProvince " + posProvince);
			lineExtn.setExtnPOSProvince(posProvince);
    	} else {
    		lineExtn.setExtnPOSProvince("");
    	}

		lineExtn.setExtnTaxProvince(line.getTaxProvince());
		lineExtn.setExtnPOSTenderDT(SOCUtility.formatDate(line.getReceiptDate()));		
		lineExtn.setExtnIsOpenBoxItem(isOpenBox);
		
		// only for return or exchange orders
		if (line.isReturnLine() || line.isExchangeLine()) { 
			
			// ExtnDCdropoffFlag
			if ("CD".equals(line.getLineRetAttribute3())) {
				lineExtn.setExtnDCdropoffFlag("Y");	
			} else {
				lineExtn.setExtnDCdropoffFlag("N");
			}
			
			// ExtnPOSEligible
			if (line.getQuantityReceived() == line.getQuantityShipped() && 
					line.getQuantityReceived() == line.getOrderedQuantity()) {
				lineExtn.setExtnPOSEligible("Y");
			} else {
				lineExtn.setExtnPOSEligible("N");
			}

		} else {
			lineExtn.setExtnDCdropoffFlag(""); // by default set it to blank
			lineExtn.setExtnPOSEligible(""); // by default set it to blank
		}
		
		lineExtn.setExtnIsPond(""); // set it to blank for now
		lineExtn.setExtnPondID(""); // set it to blank for now
		
		String swingByStore = line.getSwingByStore(); 
		if ("DC".equals(swingByStore)) {
			swingByStore = "";
		} else {
			swingByStore = (line.getPosStoreNo() == null) ? "" : line.getPosStoreNo();
		}
		lineExtn.setExtnSwingByStore(swingByStore);

		if (line.getSwingByStore() != null && !SOCConstants.EMPTY_STRING.equals(line.getSwingByStore())) {
			lineExtn.setExtnIsSwingBy("Y");
		}
		else {
			lineExtn.setExtnIsSwingBy("N");
		}
		
		lineExtn.setExtnIsVendorModelItem(""); // set it to blank for now										
		String restockingFeeFlag = ((RestockingFeeCategory.isItemCategoryExists(line.getItemCategory())) == true) ? "Y" : "N";		
		lineExtn.setExtnRestockingFeeFlag(""+restockingFeeFlag);			

//		lineExtn.setExtnWarrantySKU(""); // set or replace the SKU based on warranty type
		lineExtn.setExtnReverseDoorHinge("N"); // set it to N by default				
		orderLine.setOrderLineExtension(lineExtn);
	}	
	
	/**
	 * Creates an DerivedFrom for an OrderLine.
	 * 
	 * @param orderLine
	 * @param line
	 */
	public void createDerivedFrom(OpenSalesOrderDefinition orderDef, OrderLine orderLine, COFIOrderLine line) 
	throws SOCException {
		
		log.info("-----------------------------------");
		log.info("Create DerivedFrom");
		log.info("-----------------------------------");

		String headerID = line.getLineRetAttribute1();
		String orderNumber = "";
		ArrayList<String> orderNumbers = null;
		
		if (headerID != null) {
			orderNumbers = orderDAO.getOrderNumber(line.getLineRetAttribute1());
			if (!orderNumber.isEmpty()) {
				orderNumber = orderNumbers.get(0);
			}	
		}
												
		DerivedFrom derivedFrom = new DerivedFrom();
		derivedFrom.setDocumentType("0001"); // always sale order
		if (SOCConstants.EMPTY_STRING.equals(orderNumber)) {
			derivedFrom.setOrderNo(""+line.getOrderNumber());
		} else {
			derivedFrom.setOrderNo(orderNumber);
		}
		
		derivedPrimeLineNo++;
		derivedFrom.setPrimeLineNo(orderLine.getPrimeLineNo());
		derivedFrom.setEnterpriseCode("BAY");
		derivedFrom.setSubLineNo("1");
		orderLine.setDerivedFrom(derivedFrom);		
	}
			
	/**
	 * Creates an OrderLineOption for an OrderLine.
	 * 
	 * @param orderLine
	 * @param line
	 */
	public void createOrderLineOption(OrderLine orderLine, SalvageLine line) {
		OrderLineOption orderLineOption = new OrderLineOption();
		orderLineOption.setOptionDescription(line.getItemDesc());
		orderLineOption.setOptionItemId(line.getItemID());
		orderLineOption.setOptionUOM(line.getUnitOfMeasure());
		orderLineOption.setUnitPrice(line.getUnitPrice().setScale(2).toString());		
		orderLine.addOrderLineOption(orderLineOption);		
	}	
	
	/**
	 * Create an Item for an OrderLine.
	 * 
	 * @param orderLine
	 * @param line
	 */
	public void createItemInfo(OrderLine orderLine, COFIOrderLine line) {		
		String subinventory = line.getSubInventory();		
		String productClass = (subinventory == null) ? "" : subinventory;
		if (subinventory!=null && (subinventory.equals(SOCConstants.SUBINVENTORY_FLOOR_MODEL))) {
			productClass = SOCConstants.SUBINVENTORY_AS_IS;
		}

		Item item = new Item();
    	if(SOCConstants.LINE_TYPE_DEL.equals(line.getItemType())) {
    		item.setItemID(SOCConstants.MCF_DEL_SKU);
    	}	
    	else {    		
    		if ("627".equals(line.getItemCategory())) { // if left handed fridge
    			// replace the SKU number with the right handed fridge SKU number
    			item.setItemID(leftSku2rightSku.get(line.getItemSKU()));
    			orderLine.getOrderLineExtension().setExtnReverseDoorHinge("Y");
    		}
    		else {
    			orderLine.getOrderLineExtension().setExtnReverseDoorHinge("N");
    			item.setItemID(line.getItemSKU());
    		}	
    	}

		item.setItemDescription(line.getItemDescription());
		item.setItemShortDesc(line.getItemDescription());	
		item.setItemWeight(line.getUnitWeight() == null ? "" : line.getUnitWeight().setScale(2,BigDecimal.ROUND_HALF_UP).toString());
		item.setItemWeightUOM((line.getWeightUOMCode() == null)? "" : line.getWeightUOMCode());
		item.setProductLine((line.getItemCatalogGroupId() == null) ? "" : line.getItemCatalogGroupId());
		item.setProductClass(productClass);
		item.setUnitCost(line.getUnitListPrice().setScale(2).toString());
		
		if (SOCConstants.PRIMARY_UOM_WTY.equals(line.getItemType()) || SOCConstants.PRIMARY_UOM_WRFEE.equals(line.getItemType())) {
			item.setUnitOfMeasure(SOCConstants.PRIMARY_UOM_DAYS);
		} else if (SOCConstants.PRIMARY_UOM_DEL.equals(line.getItemType())) {
			item.setUnitOfMeasure(SOCConstants.PRIMARY_UOM_MIN);
		} else {
			item.setUnitOfMeasure(SOCConstants.PRIMARY_UOM_EACH);
		}				
		orderLine.setItem(item);		
	}	
	
	/**
	 * Creates a LinePriceInfo.
	 * 
	 * @TODO ClosedPriceAdjustments needs to be subtracted for UnitPrice
	 * 
	 * @param orderLine
	 * @param line
	 */
	public void createLinePriceInfo(OrderLine orderLine, COFIOrderLine line) {
		LinePriceInfo linePriceInfo = new LinePriceInfo();
		if (line.getTaxValue() != null && (line.getTaxValue().compareTo(new BigDecimal("0")) == 1)) {
			linePriceInfo.setTaxableFlag("Y");	
		} else {
			linePriceInfo.setTaxableFlag("N");
		}
		
		if ("Y".equals(linePriceInfo.getTaxableFlag())) {
			linePriceInfo.setTaxExemptionCertificate("");
		} else {
			linePriceInfo.setTaxExemptionCertificate(line.getTaxExemptCertificate());
		}
		
		linePriceInfo.setUnitPrice(line.getUnitSellingPrice().setScale(2).toString()); // need to implement logic
		orderLine.setLinePriceInfo(linePriceInfo);				
	}		
	
	/**
	 * Creates a line charge for different item types
	 * 
	 * Rules to create line charges:
	 * -----------------------------
	 * 1. If item type is EFEE then it will be line charges for sales order.
	 * 2. If item type is USE then it will be a line charge for return order.
	 * 3. Line charges will be create for discounts too. For all discounts one line charge will 
	 *    be created. set ChargeCategory and ChargeName as DISCOUNT. This will be created if 
	 *    unit price and unit selling price are different for a line.
	 * 4. Charge Amount for a discount lines will be calculated by subtracting unit selling price
	 *    from unit list price. If the charge amount is negative then set ChargeCategory and
	 *    ChargeName as CHARGE and pass the positive amount.
	 * 
	 * @TODO Create LineCharge if the charge amount is negative.
	 * @TODO Implement logic for usage fee. 
	 * 
	 * @param orderLine
	 * @param line
	 * @throws SQLException
	 */
	public void createLineCharge(OrderLine orderLine, COFIOrderLine line) 
	throws SOCException {
		
    	BigDecimal unitSellingPrice = line.getUnitSellingPrice();
    	BigDecimal unitListPrice = line.getUnitListPrice();
    	Integer quantity = line.getOrderedQuantity();
    	LineCharge lineCharge = null;
    	    	
    	if(unitListPrice.compareTo(unitSellingPrice)==1) {
			// Adding a line charge
        	lineCharge = new LineCharge();
	    	BigDecimal chargeAmt = (unitListPrice.subtract(unitSellingPrice)).multiply(new BigDecimal(quantity)).setScale(2);
			lineCharge.setChargePerLine(chargeAmt);
			lineCharge.setChargePerUnit(line.getUnitSellingPrice().setScale(2).toString());    	
			lineCharge.setChargeCategory(SOCConstants.DISCOUNT);
			lineCharge.setChargeName(SOCConstants.DISCOUNT);
    	}
    	else if (unitSellingPrice.compareTo(unitListPrice)==1) {
        	lineCharge = new LineCharge();
	    	BigDecimal chargeAmt = (unitListPrice.subtract(unitSellingPrice)).multiply(new BigDecimal(quantity)).setScale(2);
			lineCharge.setChargePerLine(chargeAmt);
			lineCharge.setChargePerUnit(line.getUnitSellingPrice().setScale(2).toString());    	
			lineCharge.setChargeCategory(SOCConstants.CHARGE);
			lineCharge.setChargeName(SOCConstants.CHARGE);
    	}
    	
    	// need to handle if the charge amount is negative, convert it as charge
		if (lineCharge != null) {
			// convert it as LineCharge for return lines only.
	    	if (SOCConstants.LINE_TYPE_USE.equals(line.getItemType())) {
	    		lineChargesList.add(lineCharge);
	    		lineChargesMap.put(lineCharge, line);
	    	// convert it as LineCharge for sale and exchange lines only.	
	    	} else if (SOCConstants.LINE_TYPE_EFEE.equals(line.getItemType())) {
	    		if (!line.isReturnLine()) {
	    			orderLine.addLineCharge(lineCharge);
	    		}
	    	}
	    	else {
	    		orderLine.addLineCharge(lineCharge);
	    	}
		}
	}
			
	/**
	 * Creates a LineTax for an OrderLine
	 *  
	 * @param orderLine
	 * @param line
	 */
	public void createLineTax(OrderLine orderLine, COFIOrderLine line) {
		
    	LineTax lineTax = null;
		BigDecimal gstTax = (line.getGstTax() == null) ? new BigDecimal("0") : line.getGstTax();
		BigDecimal pstTax = (line.getPstTax() == null) ? new BigDecimal("0") : line.getPstTax();
		BigDecimal hstTax = (line.getHstTax() == null) ? new BigDecimal("0") : line.getHstTax();
		
		if(MCFConverter.isHSTEligible(line)) {
			BigDecimal taxAmt = new BigDecimal("0");
			BigDecimal taxPercentage = new BigDecimal("0");
			
			if(hstTax.compareTo(new BigDecimal("0"))==1) {
				taxAmt = hstTax;
				taxPercentage = line.getHstPercent();
			}
			else {
				if(gstTax.compareTo(new BigDecimal("0"))==1) {
					taxAmt = gstTax;
					taxPercentage = line.getGstPercent();
				}
				if(pstTax.compareTo(new BigDecimal("0"))==1) {
					taxAmt = taxAmt.add(pstTax);
					taxPercentage = taxPercentage.add(line.getPstPercent());
				}
			}
			if(taxAmt.compareTo(new BigDecimal("0"))==1) {
				lineTax = new LineTax();
				lineTax.setChargeCategory(SOCConstants.CHARGE_NAME_PRICE);
				lineTax.setChargeName(SOCConstants.EMPTY_STRING);
				lineTax.setTaxName(SOCConstants.TAX_NAME_HST);
				lineTax.setTax(taxAmt.setScale(2));
				lineTax.setTaxPercentage(taxPercentage.toString());
				orderLine.addLineTax(lineTax);
			}			
		}
		else {
			if(gstTax.compareTo(new BigDecimal("0"))==1) {
				lineTax = new LineTax();
				lineTax.setChargeCategory(SOCConstants.CHARGE_NAME_PRICE);
				lineTax.setChargeName(SOCConstants.EMPTY_STRING);
				lineTax.setTax(gstTax.setScale(2));
				lineTax.setTaxPercentage(line.getGstPercent().toString());
				lineTax.setTaxName(SOCConstants.TAX_NAME_GST);
				orderLine.addLineTax(lineTax);
			}
			
			if(pstTax.compareTo(new BigDecimal("0"))==1) {
				lineTax = new LineTax();
				lineTax.setChargeCategory(SOCConstants.CHARGE_NAME_PRICE);
				lineTax.setChargeName(SOCConstants.EMPTY_STRING);
				lineTax.setTax(pstTax.setScale(2));
				lineTax.setTaxPercentage(line.getPstPercent().toString());
				lineTax.setTaxName(SOCConstants.TAX_NAME_PST);
				orderLine.addLineTax(lineTax);
			}
			
			if(hstTax.compareTo(new BigDecimal("0"))==1) {
				lineTax = new LineTax();
				lineTax.setChargeCategory(SOCConstants.CHARGE_NAME_PRICE);
				lineTax.setChargeName(SOCConstants.EMPTY_STRING);
				lineTax.setTax(hstTax.setScale(2));
				lineTax.setTaxPercentage(line.getHstPercent().toString());
				lineTax.setTaxName(SOCConstants.TAX_NAME_HST);
				orderLine.addLineTax(lineTax);
			}
		}
	}
		
	public HashMap<String, OrderLine> getLinesMap() {
		return linesMap;
	}

	public void setLinesMap(HashMap<String, OrderLine> linesMap) {
		this.linesMap = linesMap;
	}

	/**
	 * Set the ExtnWarrantySKU attribute
	 * 
	 * @param orderDef
	 */
	public void setExtnWarrantySKU(OpenSalesOrderDefinition orderDef) {
log.info("setExtnWarrantySKU...");		
		// FurnitureWarranty
		String warrantyFeeSKU  = null;
		if(orderDef.getWFREELinesList() != null && orderDef.getWFREELinesList().size() > 0) {
			log.info("WRFEE line exists...");			
			OrderLine wrfeeLine = orderDef.getWFREELinesList().get(0);
			Item wrfeeLineItem = wrfeeLine.getItem();			
			if(wrfeeLineItem!=null) {
				warrantyFeeSKU = wrfeeLineItem.getItemID();
			} else {
				log.info("WFREE line is null");
			}
		}
		
		if(orderDef.getFunitureWtyLinesList() != null && orderDef.getFunitureWtyLinesList().size() > 0) {
			log.info("Furniture WTY line exists...");
			Iterator<OrderLine> iterFurniture= orderDef.getFunitureWtyLinesList().iterator();
			while(iterFurniture.hasNext()) {				
				OrderLine orderLine = iterFurniture.next();
				String serviceRefLineId = orderLine.getServiceRefLineId();
				
				if(serviceRefLineId!=null) {
					OrderLine itemLine = getLinesMap().get(serviceRefLineId);
					if(itemLine!=null) {
						OrderLineExtension itemLineExtn = itemLine.getOrderLineExtension();
						if(itemLineExtn!=null) {
							itemLineExtn.setExtnWarrantySKU(warrantyFeeSKU);
						}
					} else {
						log.info("OrderLine is null for " + serviceRefLineId + ", cannot set warranty sku");
					}
				} else {
					log.info("serviceRefLineId is null, cannot set warranty sku");
				}
			}
		}

		if(orderDef.getNonFunitureWtyLinesList() != null && orderDef.getNonFunitureWtyLinesList().size() > 0) {
log.info("Non Furniture WTY line exists...");			
			Iterator<OrderLine> iterNonFurniture = orderDef.getNonFunitureWtyLinesList().iterator();
			while(iterNonFurniture.hasNext()) {
				OrderLine orderLine = iterNonFurniture.next();
				String serviceRefLineId = orderLine.getServiceRefLineId();
				
				if(serviceRefLineId!=null) {
					OrderLine itemLine = getLinesMap().get(serviceRefLineId);					
					if(itemLine!=null) {
						Item wtyLineItem = orderLine.getItem();
						String warrantySKU  = null;
						if(wtyLineItem!=null) {
							warrantySKU = wtyLineItem.getItemID();
						}
						
						OrderLineExtension itemLineExtn = itemLine.getOrderLineExtension();
						if(itemLineExtn!=null) {						
							itemLineExtn.setExtnWarrantySKU(warrantySKU);
						}
					}
				}
			}
		}
	}
	
	/**
	 * Associates the Usage Fee with respective order lines
	 * 
	 * @param orderDef
	 */
	private void associateUsageFee(OpenSalesOrderDefinition orderDef) {
		LineCharge lc = null;
		if (lineChargesList != null && lineChargesList.size() > 0) {
			Iterator<LineCharge> itr = lineChargesList.iterator();
			while (itr.hasNext()) {
				lc = itr.next();
				break;				
			}
		}
		
		COFIOrderLine line = lineChargesMap.get(lc);
log.info("associateUsageFee " + line);		
		if (line != null) {
			OrderLine returnLine = findReturnOrderLine(line);
			if (returnLine != null) {
				returnLine.addLineCharge(lc);
	log.info("Associated Line Charge is " + lc);			
			} else {
				log.info("ReturnLine is null, cannot associate usage fee");
			}
		} else {
			log.info("Line is null, cannot associate usage fee");
		}
	}
		
	
	/**
	 * Find the return order line for usage fee association
	 * 
	 * @param line
	 * @return
	 */
	private OrderLine findReturnOrderLine(COFIOrderLine line) {		
		log.info("Return Lines " + returnLinesMap);		
		Iterator<OrderLine> itr = returnLinesMap.values().iterator();
		while (itr.hasNext()) {
			OrderLine returnLine = itr.next();
			String itemCategory = line.getItemCategory();
			if (RestockingFeeCategory.isItemCategoryExists(itemCategory)) {
				String itemSKU = line.getItemSKU();
				if ("58195785".equals(itemSKU)) {
					if (RestockingFeeCategory.isItemExistsInElectronics(itemSKU)) {
						return returnLine;
					}
				} else if ("58212374".equals(itemSKU)) {
					if (RestockingFeeCategory.isItemExistsInMattress(itemSKU)) {
						return returnLine;
					}	    					
				} else if ("58213000".equals(itemSKU)) {
					if (RestockingFeeCategory.isItemExistsInFurniture(itemSKU)) {
						return returnLine;
					}
				}
			}
		}
		return null;
	}

	public int getRecordsFetched() {
		return d_recordsFetched;
	}
	
	public int getOrdersNotConverted() {
		return d_ordersNotConverted;
	}
	
	public int getCountXMLCreated() {
		return d_xmlCounter;
	}
	
    public ArrayList<Long> getConvertedOrderList() {
    	return convertedOrdersList;
    }
    
    public ArrayList<Long> getNotConvertedOrderList() {
    	return notConvertedOrdersList;
    }    
}